#import "WordsView.h"
#import <math.h>
#import "wraps.h"

// this code is copyright Darcy Brockbank, 1993
//
// You may freely reuse and distribute this code in any way shape or
// form, provided that this notice stays intact.
//
// darcy@hasc.ca, samurai@cs.mcgill.ca
//
// If you do improve this thing, send me a copy!
//
// - darcy

@implementation WordsView

#define MINX -50.0
#define MINY -10.0
#define SIZE 64.0

- writeThresholdDefault:sender
{
	char tmp[128];
	sprintf(tmp,"%u",threshold);
	NXWriteDefault([NXApp appName],"WordsSpeed",tmp);
	return self;
}

- writeClearAfterDefault:sender
{
	char tmp[128];
	sprintf(tmp,"%d",clearAfter);
	NXWriteDefault([NXApp appName],"WordsClearAfter",tmp);
	return self;
}


- writeBackingDefault:sender
{
	char tmp[128];
	sprintf(tmp,"%d",gray);
	NXWriteDefault([NXApp appName],"WordsBacking",tmp);
	return self;
}

- setThreshold:sender
{
	threshold = [sender intValue];
	[self perform:@selector(writeThresholdDefault:)
		with:self
		afterDelay:1000
		cancelPrevious:YES];
	return self;
}

- setClearAfter:sender;
{
	clearAfter = [sender intValue];
	[self perform:@selector(writeClearAfterDefault:)
		with:self
		afterDelay:1000
		cancelPrevious:YES];
	return self;
}

- loadWords;
{
	NXStream *s = NXMapFile("/usr/dict/words",NX_READONLY);
	NXGetMemoryBuffer(s,&words,&len,&maxlen);
	fontNames = [[FontManager new] availableFonts];
	if (fontNames) {
		for(numFonts = 0;fontNames[numFonts];numFonts++);
	}
	return self;
}

- prepFont
{
	unsigned num = ((unsigned)random()) % numFonts;
	float size = SIZE; //floor(32.0 + (64.0 * ((float)random())/(float)INT_MAX));
	font = [Font newFont:fontNames[num] size:size matrix:NX_IDENTITYMATRIX];
	[font set];
	return self;
}

- drawSelf:(const NXRect *)r :(int)c
{
	if (!r || !c || c==2) return self;

	NXSetColor(NX_COLORBLACK);
	NXRectFill(r);
	return self;
}

- prepColor;
{
	blue = ((float)((unsigned)random()))/(float)INT_MAX;
	red = ((float)((unsigned)random()))/(float)INT_MAX;
	green = ((float)((unsigned)random()))/(float)INT_MAX;
	currentColor = NXConvertRGBToColor(red,blue,green);
	return self;
}


- prepPosition;
{
	xpos = (((unsigned)random()) % (unsigned)((maxCoord.x-MINX))) +MINX;
	ypos = (((unsigned)random()) % (unsigned)((maxCoord.y-MINY))) +MINY;
	return self;
}

- prepWord;
{
	unsigned i = ((unsigned)random()) % (maxlen-1);
	int j;
	for(;(words[i]!='\n' && i);i--);
	for(j=0,i++;words[i]!='\n' && i<maxlen;i++,j++) currentWord[j]=words[i];
	currentWord[j]='\0';
	return self;
}

- prep;
{
	if (iteration++ > clearAfter) {
		NXSetColor(NX_COLORBLACK);
		NXRectFill(&bounds);
		iteration=0;
	}
	[self prepFont];
	[self prepColor];
	[self prepPosition];
	[self prepWord];
	return self;
}

- setGray:sender
{
	gray = [[sender selectedCell] tag];
	[self perform:@selector(writeBackingDefault:)
		with:self
		afterDelay:1000
		cancelPrevious:YES];
	return self;
}

- oneStep
{
	static unsigned lastTime = 0;
	unsigned thisTime = currentTimeInMs();
	
	if (thisTime-lastTime<threshold) return self;
	lastTime = thisTime;
	[self prep];
#if 0
	NXSetColor(NX_COLORBLACK);
	PSmoveto(xpos-2.0,ypos-2.0);
	PSshow(currentWord);
	NXSetColor(currentColor);
	PSmoveto(xpos,ypos);
	PSshow(currentWord);
#else
	if (gray){
		PSdostuff(currentWord,xpos-1.0,ypos+1.0,xpos+1.0,ypos-1.0,xpos,ypos,red,green,blue);
	} else {
		PSdostuffnowhite(currentWord,xpos-1.0,ypos+1.0,xpos+1.0,ypos-1.0,xpos,ypos,red,green,blue);
	}
#endif
	return self;
}

- (BOOL)useBufferedWindow
{
	return YES;
}

- initFrame:(const NXRect *)frameRect
{
	const char *t;
	[super initFrame:frameRect];
	[self allocateGState];		// For faster lock/unlockFocus
	[self setClipping:NO];		// even faster...
//	buffer = [[NXImage alloc] init];
	[self newViewSize];
	srandom(time(0));
	if (t = NXReadDefault([NXApp appName],"WordsSpeed")){
		threshold = atoi(t);
	} else {
		threshold = 200;
	}
	if (t= NXReadDefault([NXApp appName],"WordsClearAfter")){
		clearAfter = atoi(t);
	} else {
		clearAfter = 500;
	}
	if (t= NXReadDefault([NXApp appName],"WordsBacking")){
		gray = atoi(t);
	} else {
		gray = 1;
	}
	return self;
}

- sizeTo:(NXCoord)width :(NXCoord)height
{
	[super sizeTo:width :height];
	[self newViewSize];
	return self;
}

- newViewSize
{
	if (oldSize.width == bounds.size.width &&
			oldSize.height == bounds.size.height)
	{
		return self;
	}else{
		oldSize.width = bounds.size.width;
		oldSize.height = bounds.size.height;
	}
	maxCoord.x = bounds.size.width-150.0;
	maxCoord.y = bounds.size.height;
	if (maxCoord.x < 0) maxCoord.x = 0;
	if (maxCoord.y < 0) maxCoord.y = 0;
//	size.height = SIZE+2.0;
//	size.width = oldSize.width;
//	[buffer setSize:&size];
	if ([self window]){
		[self display];
	}
	return self;
}

- (const char *)windowTitle
{
	return "WordsView";
}


- inspector:sender
{
    char buf[MAXPATHLEN];

	if (!sharedInspectorPanel){
		sprintf(buf,"%s/WordsView.nib",[sender moduleDirectory:"Words"]);
		[NXApp loadNibFile:buf owner:self withNames:NO];
		[self loadWords];
		[speedSlider setIntValue:threshold];
		[clearSlider setIntValue:clearAfter];
		[grayMatrix selectCellWithTag:gray];
	}
	return sharedInspectorPanel;
}

@end
